package com.lalilu.lmedia.entity

import android.support.v4.media.MediaMetadataCompat
import com.lalilu.lmedia.extension.ChineseToPinyinTransformer
import com.lalilu.lmedia.extension.SearchTextManager
import com.lalilu.lmedia.extension.Sortable

/**
 * 用于为搜索功能存储全文匹配索引的基类
 */
interface FullTextMatchable {
    var matchStr: String
    fun getMatchSource(): String
}

interface PinyinFirstLetterMatchable {
    var pinyinMatchStr: String
    fun getPinyinMatchSource(): String
}

abstract class BaseMatchable : PinyinFirstLetterMatchable, FullTextMatchable {
    override var matchStr: String = ""
        get() = field.takeIf { it.isNotEmpty() }
            ?: SearchTextManager.createPatternString(getMatchSource()).also { field = it }

    override var pinyinMatchStr: String = ""
        get() {
            if (field.isNotEmpty()) return field
            field = ChineseToPinyinTransformer.transform(getPinyinMatchSource())
                ?: getPinyinMatchSource()
            return field
        }
}

abstract class Item : BaseMatchable(), Sortable {
    abstract val id: String
    abstract val name: String
    var blocked: Boolean = false

    val metadataCompat: MediaMetadataCompat by lazy {
        MediaMetadataCompat.Builder().initMetadata().build()
    }

    override fun getMatchSource(): String = name
    override fun getPinyinMatchSource(): String = name
    override fun requireTitle(): String = name

    /**
     * 重载此方法用于完善metadataCompat的转换逻辑
     */
    open fun MediaMetadataCompat.Builder.initMetadata(): MediaMetadataCompat.Builder {
        return this
    }
}

abstract class MusicParent : Item() {
    abstract val songs: List<LSong>

    override fun requireItemsCount(): Long = songs.size.toLong()
    override fun requireItemsDuration(): Long =
        songs.fold(0L) { acc, item -> acc + item.durationMs }

    override fun requireFileSize(): Long =
        songs.fold(0L) { acc, item -> acc + item.size }
}

/**
 * 根据子项判断自身是否应该被标记为已屏蔽
 */
fun <T : MusicParent> List<T>.markBlockedByItems() = onEach {
    it.blocked = !it.songs.any { song -> !song.blocked }
}